iT邦幫忙

2023 iThome 鐵人賽

DAY 10
0
自我挑戰組

模仿知名網站的外觀系列 第 10

【Day10】模仿知名網站的外觀 Instagram(10) 建立新貼文

  • 分享至 

  • xImage
  •  

我們上回已經完成Instagram的首頁區塊了,接下來我們要繼續打造新的區塊,這次要編寫的是建立新貼文的區塊,也就是按下側邊欄的Create按鈕時會出現的區塊,雖然真實的Instagram能在建立貼文時裁切和套用濾鏡,但是我們的專案會省略這些部分,專注於發佈新貼文的部分。

我們在Post資料夾底下,新增CreatePostModal.jsx,是建立新貼文部分的主體,按下Create按鈕會彈出的視窗,內容有一部分是之前複製過的Chakra UI範例。

import {
	Modal,
	ModalBody,
	ModalCloseButton,
	ModalContent,
	ModalHeader,
	ModalOverlay,
} from "@chakra-ui/react";
import React from "react";

const CreatePostModal = ({ onClose, isOpen }) => {
	return (
		<div>
			<Modal size={"4xl"} onClose={onClose} isOpen={true} isCentered>
				<ModalOverlay />
				<ModalContent>
					<ModalHeader>Modal Title</ModalHeader>
					<ModalCloseButton />
					<ModalBody></ModalBody>
				</ModalContent>
			</Modal>
		</div>
	);
};

export default CreatePostModal;

來到HomePage.jsx,在最後的部分加上。

import React from 'react'
import StoryCircle from "../../Components/Story/StoryCircle"
import HomeRight from "../../Components/HomeRight/HomeRight"
import PostCard from "../../Components/Post/PostCard"
import CreatePostModal from "../../Components/Post/CreatePostModal"

const HomePage = () => {
  return (
    <div>
      <div className="mt-10 flex w-[100%] justify-center">
        <div className="w-[44%] px-10">
          <div className="flex space-x-2 border p-4 rounded-md justify-start w-full">
            {
              [1, 1, 1].map((item) => (
                <StoryCircle />
              ))
            }
          </div>

          <div className="space-y-10 w-full mt-10">
            {[1, 1].map((item) => <PostCard />)}
          </div>
        </div>
        <div className="w-[35%]">
          <HomeRight />
        </div>
      </div>

      <CreatePostModal />
    </div>
  )
}

export default HomePage

確認一下,程式有沒有正常運作,要是啪的一下子寫一堆程式碼,最後才發現不能正常顯示就不好了。

Untitled

我們開始編寫部分排版,修改CreatePostModal.jsx。

import {
	Button,
	Modal,
	ModalBody,
	ModalContent,
	ModalOverlay,
} from "@chakra-ui/react";
import React from "react";

const CreatePostModal = ({ onClose, isOpen }) => {
	return (
		<div>
			<Modal size={"4xl"} onClose={onClose} isOpen={true} isCentered>
				<ModalOverlay />
				<ModalContent>
					<div className="flex justify-between py-1 px-10 items-center">
						<p>Create New Post</p>
						<Button variant={"ghost"} size="sm" colorScheme={"blue"}>
							Share
						</Button>
					</div>
					<ModalBody></ModalBody>
				</ModalContent>
			</Modal>
		</div>
	);
};

export default CreatePostModal;

Untitled

修改CreatePostModal.jsx,繼續顯示出上傳圖片或影片的文字。

import {
	Button,
	Modal,
	ModalBody,
	ModalContent,
	ModalOverlay,
} from "@chakra-ui/react";
import React from "react";
import { FaPhotoVideo } from "react-icons/fa";

const CreatePostModal = ({ onClose, isOpen }) => {
	return (
		<div>
			<Modal size={"4xl"} onClose={onClose} isOpen={true} isCentered>
				<ModalOverlay />
				<ModalContent>
					<div className="flex justify-between py-1 px-10 items-center">
						<p>Create New Post</p>
						<Button variant={"ghost"} size="sm" colorScheme={"blue"}>
							Share
						</Button>
					</div>
					<hr />
					<ModalBody>
						<div>
							<div>
								<div>
									<div>
										<FaPhotoVideo className="text-3xl" />
										<p>Drag photos and videos here</p>
									</div>
								</div>
							</div>
						</div>
					</ModalBody>
				</ModalContent>
			</Modal>
		</div>
	);
};

export default CreatePostModal;

Untitled

接下來,我們處理上傳的部分,先寫出大概的外觀,實際上傳的部分以後再說,將CreatePostModal.jsx修改成以下內容:

import {
	Button,
	Modal,
	ModalBody,
	ModalContent,
	ModalOverlay,
} from "@chakra-ui/react";
import React, { useState } from "react";
import { FaPhotoVideo } from "react-icons/fa";
import './CreatePostModal.css';

const CreatePostModal = ({ onClose, isOpen }) => {
	const [isDragOver, setIsDragOver] = useState(false);
	const [file, setFile] = useState();

	const handleDrop = (e) => {
		e.preventDefault();
		const droppedFile = e.dataTransfer.file[0];
		//檢查檔案類型是圖片或影片才能上傳
		if (
			droppedFile.type.startsWith("image/") ||
			droppedFile.type.startsWith("video/")
		) {
			setFile(droppedFile);
		}
	};

	const handleDragOver = (e) => {
		e.preventDefault();
		e.dataTransfer.dropEffect = "copy";
		setIsDragOver(true);
	};

	const handleDragLeave = () => {
		setIsDragOver(false);
	};

	//上傳檔案時,確認是不是圖片或影片
	const handleOnChange = (e) => {
		const file = e.target.file[0];
		if (
			file &&
			(file.type.startsWith("image/") || file.type.startsWith("video/"))
		) {
			setFile(file);
		} else {
			setFile(null);
			alert("Please upload an image or video");
		}
	};

	return (
		<div>
			<Modal size={"4xl"} onClose={onClose} isOpen={true} isCentered>
				<ModalOverlay />
				<ModalContent>
					<div className="flex justify-between py-1 px-10 items-center">
						<p>Create New Post</p>
						<Button variant={"ghost"} size="sm" colorScheme={"blue"}>
							Share
						</Button>
					</div>
					<hr />
					<ModalBody>
						<div>
							<div className="w-[50%]">
								<div
									onDrop={handleDrop}
									onDragOver={handleDragOver}
									onDragLeave={handleDragLeave}
									className="drag-drop h-full"
								>
									<div>
										<FaPhotoVideo className="text-3xl" />
										<p>Drag photos and videos here</p>
									</div>
									<label htmlFor="file-upload" className="custom-file-upload">
										Select From Computer
									</label>

									<input
										className="file-input"
										type="file"
										id="file-upload"
										accept="image/*, video/*"
										onChange={handleOnChange}
									/>
								</div>
							</div>
						</div>
					</ModalBody>
				</ModalContent>
			</Modal>
		</div>
	);
};

export default CreatePostModal;

isDragOver代表是否有內容拖曳到網頁中。

handleDrop的作用是當檔案拖曳進來時,確認檔案類型,如果符合,就設定成上傳的檔案。

handleDragOver有檔案拖動到網頁上就會做裏面的內容。

handleDragLeave將檔案移動到網頁上後又離開,就會執行裏面的程式碼。

handleOnChange按下按鈕上傳檔案時會進行裏面的動作。

在Post資料夾底下,新增CreatePostModal.css。

.drag-drop{
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    padding: 2rem;
    font-size: 1.2rem;
    color: #999;
    border-radius: 5px;
    cursor: pointer;
}

.drag-drop p{
    margin: 0 0 1rem;
}

.custom-file-upload{
    padding: .5rem 1rem;
    font-weight: 600;
    color: white;
    background-color: #0095F6;
    border: 1px solid #0095F6;
    cursor: pointer;
}

.custom-file-upload:hover{
    background-color: #1877F2;
    border-color: #1877F2;
}

input[type="file"]{
    display: none;
}

.fileInput{
    display: none;
}

完成後的外觀是這樣,可以拖曳檔案到這個地方,也可以按下藍色的按鈕上傳內容,雖然什麼也不會發生,因為我們沒寫實際的上傳處理。

Untitled


上一篇
【Day9】模仿知名網站的外觀 Instagram(9) 編寫Comment區塊-2
下一篇
【Day11】模仿知名網站的外觀 Instagram(11) 建立新貼文-2
系列文
模仿知名網站的外觀30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言